package com.aike.user_center_practice.service.impl;

import com.aike.user_center_practice.common.BaseResponse.ErrorCode;
import com.aike.user_center_practice.exception.BusinessException;
import com.aike.user_center_practice.mapper.UserMapper;
import com.aike.user_center_practice.model.domain.User;
import com.aike.user_center_practice.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.aike.user_center_practice.contant.UserConstant.*;

/**
 * 用户服务实现类
* @author TAT SUN
* @description 针对表【user】的数据库操作Service实现
* @createDate 2025-07-31 22:41:47
*/

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    // 日志管理
    final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    // 盐值：混淆密码
    private static String Salt = "abc";

    /**
     * 用户注册逻辑
     * @param userAccount 用户账号
     * @param userPassword 用户密码
     * @param checkPassword 校验密码
     * @param planeCode 星球用户校验密码
     * @return id
     */
    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword, String planeCode) {

        // 1. 校验: 非空
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword, planeCode)) {
            throw new BusinessException(ErrorCode.NULL_ERROR, "用户的名称/密码/校验码/星球编号为空"); // 直接抛出异常
        }
        if (userAccount.length() < 4){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号长度过长。"); // 直接抛出异常
        }
        if(userPassword.length() < 8 || checkPassword.length() < 8){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码长度过长。"); // 直接抛出异常
        }
        if(planeCode.length() > 5){ // 这里对星球用户进行编码，要求号码不能超过5位数
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "星球编号长度过长。"); // 直接抛出异常
        }
        // 账号不能包含特殊字符
        String ValidateStr = "\\pP|\\pS|\\s+"; // 文本字符集的校验; 正则表达式
        Matcher matcher = Pattern.compile(ValidateStr).matcher(userAccount);
        if (matcher.find()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号包含特殊字符。"); // 直接抛出异常
        }
        // 密码和校验密码相同
        if(!userPassword.equals(checkPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码和校验密码相同。"); // 直接抛出异常
        }

        // 账号不能重复 注意：这里先进行密码校验，然后才进行账号检测！！！！！ 保障性能损耗最小
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", userAccount);
        long count = this.count(queryWrapper);
        if (count > NORMAL_NUMBER_ZERO){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号已重复！");
        }

        // 对星球编号的校验，要求不能重复
        QueryWrapper<User> planeSearch = new  QueryWrapper<>();
        planeSearch.eq("planeCode", planeCode);
        long number = this.count(planeSearch);
        if (number > NORMAL_NUMBER_ZERO){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "星球编号重复！");
        }
        // 2. 加密
        String newPassword = DigestUtils.md5DigestAsHex((Salt + userPassword).getBytes());

        // 3. 向数据库插入数据
        User user = new User();
        user.setAccount(userAccount);
        user.setUserPassword(newPassword);
        user.setPlaneCode(planeCode);
        boolean save = this.save(user);
//        this.save(user)
        if (!save) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "保存错误！");
        }
        return user.getId();
    }

    /**
     * 用户登录逻辑
     *
     * @param userAccount  用户账号
     * @param userPassword 用户密码
     * @param request 用户登录注册验证
     * @return user info
     */
    @Override
    public User userLogin(String userAccount, String userPassword, HttpServletRequest request) {

        // 1. 校验: 非空
        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码和账号长度为空！"); // 直接抛出异常
        }
        if (userAccount.length() < 4){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号长度过长。"); // 直接抛出异常
        }
        if(userPassword.length() < 8){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码长度过长。"); // 直接抛出异常
        }

        // 账号不能包含特殊字符
        String ValidateStr = "\\pP|\\pS|\\s+"; // 文本字符集的校验; 正则表达式
        Matcher matcher = Pattern.compile(ValidateStr).matcher(userAccount);
        if (matcher.find()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号不能包含特殊字符！"); // 直接抛出异常
        }

        // 2. 加密
        String mdSercret = DigestUtils.md5DigestAsHex((Salt + userPassword).getBytes());

        // 账号不能重复 注意：这里先进行密码校验，然后才进行账号检测！！！！！ 保障性能损耗最小
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", userAccount);
        queryWrapper.eq("userPassword", mdSercret);

        User user = this.getOne(queryWrapper);
        logger.info("getOne info!" + user);
        if (user == null){
            logger.info("getOne info User no exist! login fail.");
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户为空"); // 直接抛出异常
        }
        // 用户脱敏
        User safeUser = getSafetyUser(user);

        // 记录用户的登录状态
        logger.info("Record user status!");
        request.getSession().setAttribute(USER_LOGIN_STATUS, safeUser);
        return user;
    }

    /**
     * 用户脱敏
     * @param user 脱敏类型
     * @return 结果
     */
    @Override
    public User getSafetyUser(User user){
        // 用户脱敏
        logger.info("user leave bad information");
        if(user == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户字符为空。"); // 直接抛出异常
        }
        User users = new User();
        users.setId(user.getId());
        users.setUsername(user.getUsername());
        users.setAccount(user.getAccount());
        users.setAvatarUrl(user.getAvatarUrl());
        users.setGender(user.getGender());
        users.setEmail(user.getEmail());
        users.setPlaneCode(user.getPlaneCode());
        users.setUserStatus(user.getUserStatus());
        users.setCreateTime(user.getCreateTime());
        users.setUserPassword(user.getUserPassword());
        users.setUpdateTime(user.getUpdateTime());
        users.setUserRole(user.getUserRole());
        return users;
    }

    /**
     * 退出登录态的接口
     * @param request 请求
     * @return 清除登录态
     */
    @Override
    public int userLogout(HttpServletRequest request) {
        request.getSession().removeAttribute(USER_LOGIN_STATUS); // 从session中清除登录态
        return NORMAL_NUMBER_ONE;
    }
}
